local base = _G
local math = base.math
module("gui")

ButtonG = {}
ButtonGMT = { __index = ButtonG }

base.setmetatable(ButtonG, { __index = ObjectG })

ButtonG.create = function(x, y, text, width, height)
  text = text or ""
  -- calculate width and height based on the styles
  local styles = get_styles('font', 'padding', 'align', 'gradient', 'press_offset') --, 'drop_shadow_offset')
  local colors = get_colors('border', 'background', 'font') --, 'drop_shadow')
  local pad = styles.padding*2
  width = width or styles.font:get_width(text) + pad
  height = height or styles.font:get_height() + pad

  local self = Object(x, y, width, height, ButtonGMT)

  self.styles = styles
  self.colors = colors
  
  self.text = text
  self.is_down = false

  return self
end

ButtonG.destroy = function(self)
  self.text = nil
  self.is_down = nil
  
  self.styles = nil
  self.colors = nil
  ObjectG.destroy(self)
end

-- handle mouse input
ButtonG.mouse_press = function(self, button, x, y)
  self.is_down = true
end

ButtonG.mouse_release = function(self, button, x, y)
  self.is_down = false
  if self:test_point(x, y) == true then
    self:on_click()
  end
end

ButtonG.redraw = function(self, delta)
  local c = self.node.canvas
  c:clear()

  local alpha = 0.5
  if self.is_down == true and self.is_hovered == true then
    alpha = 1
  elseif self.is_hovered == true then
    alpha = 0.75
  end

  local l, t, r, b = 0, -self.height, self.width, 0
  local a = alpha
  if self.is_focused then
    a = math.min(a*1.5, 1)
  end
  -- draw background
  local bg = self.colors.background
  if bg then
    c:rect(l, t, r, b)
    c:set_fill_style(bg, 1)
    c:fill()
    if self.colors.gradient and bg then
      local grad = base.LinearGradient()
      grad:stop_point1(0, -self.height, self.colors.gradient)
      grad:stop_point2(0, 0, bg)
      c:rect(l, t, r, b)
      c:set_fill_style(grad, alpha)
      c:fill_gradient()
    end
  end
  -- draw border
  if self.colors.border then
    c:rect(l - 1, t, r, b + 1)
    c:set_line_style(1, self.colors.border, a)
    c:stroke()
  end

  -- write the text
  local out = self.text
  out = self.styles.font:clamp(out, self.width, "...")
  local w = self.styles.font:get_width(out)
  -- baseline
  local bs = (self.height - self.styles.font:get_size())/2
  bs = bs - self.height
  local pad = self.styles.padding
  local x = pad
  if self.styles.align == 'center' then
    x = self.width/2 - w/2
  elseif self.styles.align == 'right' then
    x = self.width - w - pad
  end
  local yo = self.styles.press_offset
  if yo then
    if self.is_down == true and self.is_hovered == true then
      bs = bs + yo
    end
  end
  --[[
  local ds = self.colors.drop_shadow
  local dso = self.styles.drop_shadow_offset
  if ds and dso then
    c:move_to(x, bs + dso)
    c:set_font(self.styles.font, ds, alpha)
    c:write(out)
  end
  ]]
  c:move_to(x, bs)
  c:set_font(self.styles.font, self.colors.font, alpha)
  c:write(out)
end

ButtonG.update = function(self, dt)
  self:redraw(dt)
end

-- events
ButtonG.on_click = function(self)
  
end
  
Button = ButtonG.create